﻿using Newtonsoft.Json;
using System;
using System.Linq;
using System.Threading.Tasks;
using Yz.Base;

namespace Yz.Cache.Redis
{
    public class CacheRedisUitility : BaseCacheUitility, ICacheUitility
    {

        #region 从缓存中获得数据（有委托）
        /// <summary>
        /// 具体执行缓存委托或更新缓存
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="func">委托方法</param>
        /// <param name="args">至少有2个参数（从右往左（从后往前），1：是否去更新缓存，2：CacheDbTime 对象（包含时间和数据库索引）</param>
        /// <returns>T></returns>
        protected override ReturnList<T> GetDataListFromCache<T>(Delegate func, object[] args)
        {
            ReturnList<T> itemList = new ReturnList<T>();
            if (args.Length < 2)
            {
                return itemList;
            }
            var cachePara = base.GetCachePara(func, args);
            CacheRedisProvider redisHelper = GetCacheProvider(cachePara.DbNum);
            string redisValue = "";
            if (cachePara.Update || !redisHelper.KeyExists(cachePara.Key))//为了更新缓存
            {
                itemList = (ReturnList<T>)func.DynamicInvoke(args.Take(args.Length - 2).ToArray());
                if (itemList.List.Count > 0)
                {
                    redisValue = JsonConvert.SerializeObject(itemList);
                }
                redisHelper.StringSet(cachePara.Key, redisValue, cachePara.Expiry);
            }
            else
            {
                redisValue = redisHelper.StringGet(cachePara.Key);
                if (!string.IsNullOrEmpty(redisValue))
                {
                    itemList = JsonConvert.DeserializeObject<ReturnList<T>>(redisValue);
                }
            }
            return itemList;
        }
        /// <summary>
        /// 具体执行缓存委托或更新缓存
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="func">委托方法</param>
        /// <param name="args">至少有2个参数（从右往左（从后往前），1：是否去更新缓存，2：CacheDbTime 对象（包含时间和数据库索引）</param>
        /// <returns>T></returns>
        protected override async Task<ReturnList<T>> GetDataListFromCacheAsync<T>(Delegate func, object[] args)
        {
            ReturnList<T> itemList = new ReturnList<T>();
            if (args.Length < 2)
            {
                return itemList;
            }
            var cachePara = base.GetCachePara(func, args);
            CacheRedisProvider redisHelper = GetCacheProvider(cachePara.DbNum);
            string redisValue = "";
            if (cachePara.Update || await redisHelper.KeyExistsAsync(cachePara.Key) == false)//为了更新缓存
            {
                itemList = await (Task<ReturnList<T>>)func.DynamicInvoke(args.Take(args.Length - 2).ToArray());
                if (itemList.List.Count > 0)
                {
                    redisValue = JsonConvert.SerializeObject(itemList);
                }
                await redisHelper.StringSetAsync(cachePara.Key, redisValue, cachePara.Expiry);
            }
            else
            {
                redisValue = await redisHelper.StringGetAsync(cachePara.Key);
                if (!string.IsNullOrEmpty(redisValue))
                {
                    itemList = JsonConvert.DeserializeObject<ReturnList<T>>(redisValue);
                }
            }
            return itemList;
        }
        /// <summary>
        /// 具体执行缓存委托或更新缓存
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="func">委托方法</param>
        /// <param name="args">至少有2个参数（从右往左（从后往前），1：是否去更新缓存，2：CacheDbTime 对象（包含时间和数据库索引）</param>
        /// <returns>T></returns>
        protected override T GetDataFromCache<T>(Delegate func, object[] args)
        {
            T item = default(T);
            if (args.Length < 2)
            {
                return item;
            }
            var cachePara = base.GetCachePara(func, args);
            string redisValue = "";
            CacheRedisProvider redisHelper = GetCacheProvider(cachePara.DbNum);
            if (cachePara.Update || !redisHelper.KeyExists(cachePara.Key))//为了更新缓存
            {
                item = (T)func.DynamicInvoke(args.Take(args.Length - 2).ToArray());
                if (item != null)
                {
                    redisValue = JsonConvert.SerializeObject(item);
                }
                redisHelper.StringSet(cachePara.Key, redisValue, cachePara.Expiry);
            }
            else
            {
                redisValue = redisHelper.StringGet(cachePara.Key);
                if (!string.IsNullOrEmpty(redisValue))
                {
                    item = JsonConvert.DeserializeObject<T>(redisValue);
                }
            }
            return item;
        }
        /// <summary>
        /// 具体执行缓存委托或更新缓存
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="func">委托方法</param>
        /// <param name="args">至少有2个参数（从右往左（从后往前），1：是否去更新缓存，2：CacheDbTime 对象（包含时间和数据库索引）</param>
        /// <returns>Task<T></returns>
        protected override async Task<T> GetDataFromCacheAsync<T>(Delegate func, object[] args)
        {
            T item = default(T);
            if (args.Length < 2)
            {
                return item;
            }
            var cachePara = base.GetCachePara(func, args);
            CacheRedisProvider redisHelper = GetCacheProvider(cachePara.DbNum);
            string redisValue = "";
            if (cachePara.Update || await redisHelper.KeyExistsAsync(cachePara.Key) == false)//为了更新缓存
            {
                item = await (Task<T>)func.DynamicInvoke(args.Take(args.Length - 2).ToArray());
                if (item != null)
                {
                    redisValue = JsonConvert.SerializeObject(item);
                }
                await redisHelper.StringSetAsync(cachePara.Key, redisValue, cachePara.Expiry);
            }
            else
            {
                redisValue = await redisHelper.StringGetAsync(cachePara.Key);
                if (!string.IsNullOrEmpty(redisValue))
                {
                    item = JsonConvert.DeserializeObject<T>(redisValue);
                }
            }
            return item;
        }
        #endregion

        #region 查询缓存
        /// <summary>
        /// 获得缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cachePara"></param>
        /// <returns></returns>
        public T GetCache<T>(BaseParaCache cachePara)
        {
            CacheRedisProvider redisHelper = GetCacheProvider(cachePara.DbNum);
            return redisHelper.StringGet<T>(cachePara.Key);
        }
        /// <summary>
        /// 获得缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cachePara"></param>
        /// <returns></returns>
        public async Task<T> GetCacheAsync<T>(BaseParaCache cachePara)
        {
            CacheRedisProvider redisHelper = GetCacheProvider(cachePara.DbNum);
            return await redisHelper.StringGetAsync<T>(cachePara.Key);
        }
        /// <summary>
        /// 获得缓存
        /// </summary>
        /// <param name="cachePara"></param>
        /// <returns></returns>
        public string GetCache(BaseParaCache cachePara)
        {
            CacheRedisProvider redisHelper = GetCacheProvider(cachePara.DbNum);
            return redisHelper.StringGet(cachePara.Key);
        }
        /// <summary>
        /// 获得缓存
        /// </summary>
        /// <param name="cachePara"></param>
        /// <returns></returns>
        public async Task<string> GetCacheAsync(BaseParaCache cachePara)
        {
            CacheRedisProvider redisHelper = GetCacheProvider(cachePara.DbNum);
            return await redisHelper.StringGetAsync(cachePara.Key);
        }
        #endregion

        #region 设置缓存
        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cachePara"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool SetCache<T>(ParaCache cachePara, T value)
        {
            CacheRedisProvider redisHelper = GetCacheProvider(cachePara.DbNum);
            return redisHelper.StringSet(cachePara.Key, JsonConvert.SerializeObject(value), cachePara.Expiry);
        }
        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cachePara"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task<bool> SetCacheAsync<T>(ParaCache cachePara, T value)
        {
            CacheRedisProvider redisHelper = GetCacheProvider(cachePara.DbNum);
            return await redisHelper.StringSetAsync(cachePara.Key, JsonConvert.SerializeObject(value), cachePara.Expiry);
        }
        #endregion

        #region 清空缓存
        /// <summary>
        /// 删除缓存
        /// </summary>
        /// <param name="cacheKey"></param>
        /// <param name="dbNum"></param>
        /// <returns></returns>
        public bool DeleteCache(string cacheKey, int dbNum = 0)
        {
            CacheRedisProvider redisProvider = GetCacheProvider(dbNum);
            long res = redisProvider.KeyDeleteByPattern(cacheKey);
            if (res > 0)
            {
                return true;
            }
            return false;
        }
        /// <summary>
        /// 删除缓存
        /// </summary>
        /// <param name="cacheKey"></param>
        /// <param name="dbNum"></param>
        /// <returns></returns>
        public async Task<bool> DeleteCacheAsync(string cacheKey, int dbNum = 0)
        {
            CacheRedisProvider redisProvider = GetCacheProvider(dbNum);
            long res = await redisProvider.KeyDeleteByPatternAsync(cacheKey);
            if (res > 0)
            {
                return true;
            }
            return false;
        }
        private CacheRedisProvider GetCacheProvider(int dbNum)
        {
            return new CacheRedisProvider(dbNum, _cacheConfig.CachePrefixName, _cacheConfig.RedisConnStr);
        }
        #endregion 
    }
}
